﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Noris.Tools.TraceVisualiser.Pics;
using Noris.Tools.TraceVisualiser.Interface;
using Noris.Tools.TraceVisualiser.Support;

namespace Noris.Tools.TraceVisualiser.Forms
{
    internal partial class MainAppForm : Noris.Tools.TraceVisualiser.Components.DForm, IFormStatusbar
	{
		#region Konstrukce
		public MainAppForm()
		{
            this._InitBefore();
            InitializeComponent();
            this._InitAfter();
		}
		private void _InitBefore()
		{

            // 3× StripPanel (Top, Left, Right):
            this._TopStripPanel = new ToolStripPanel() { Dock = DockStyle.Top };
            this._LeftStripPanel = new ToolStripPanel() { Dock = DockStyle.Left };
            this._RightStripPanel = new ToolStripPanel() { Dock = DockStyle.Right };
            this.Controls.Add(this._LeftStripPanel);
            this.Controls.Add(this._RightStripPanel);
            this.Controls.Add(this._TopStripPanel);

            // MainMenu:
            this._InitMainMenu();

            // Zobrazit seznam Recent files v menu File:
            this.LastProjectInsertIntoMenu();

            // System Toolbar:
            this._InitSystemToolbar();

            // Function Toolbar:
            this._InitFunctionToolbar();

            // Search Toolbar:
            this._InitSearchToolbar();

            // Nyní jsou prvky UI deklarovány, a pokud chtějí reagovat (Enabled) na stav dokumentu, zde dostanou možnost:
            this.TraceDocumentActivated(null);

            // Prvotní rozmístění toolstripů:
            this.Shown += new EventHandler(_MainAppForm_Shown);

            this.MdiChildActivate += new EventHandler(_MdiChildActivate);
            
			this._OpenFileOnFirstShown = true;
		}
        /// <summary>
        /// Vytvoří MainMenu (File, Window, Function), uloží patřičné položky do instančních proměnných, a vloží jej do _TopStripPanel
        /// </summary>
        private void _InitMainMenu()
        {
            ToolStripMenuItem item;
            this._MainMenu = _CreateMenuStrip("MainMenu", DockStyle.None, ToolStripGripStyle.Visible);
            // MainMenu.File:
            item = _CreateMenuItem("MenuFile", "&Soubor",
                _CreateMenuItem("FileNew", "&Nový", PicLibrary16.Documentnew5_FromFile, (Keys)(Keys.Control | Keys.N), this._ClickMenuFileNew),
                _CreateMenuItem("FileOpen", "&Otevřít", PicLibrary16.Documentopen4_FromFile, (Keys)(Keys.Control | Keys.O), this._ClickMenuFileOpen),
                _CreateMenuItem("FileProperties", "&Vlastnosti", PicLibrary16.Documentproperties3_FromFile, Keys.None, this._ClickMenuFileProperties, ToolItemProperties.EnabledDependOnTrace),
                _CreateMenuItem("FileAuditlog", "&Auditlog", PicLibrary16.MailMarkImportant2_FromFile, Keys.None, this._ClickMenuFileAuditlog, ToolItemProperties.EnabledDependOnTrace),
                _CreateSeparator("FileSep1"),
                _CreateMenuItem("FileSave", "&Uložit", PicLibrary16.Documentsave3_FromFile, (Keys)(Keys.Control | Keys.S), this._ClickMenuFileSave, ToolItemProperties.EnabledDependOnTrace),
                _CreateMenuItem("FileSaveAs", "Uložit j&ako...", PicLibrary16.Documentsaveall_FromFile, Keys.None, this._ClickMenuFileSaveAs, ToolItemProperties.EnabledDependOnTrace),
                _CreateSeparator("FileSep2"),
                _CreateMenuItem("FileSettings", "&Konfigurace", null, Keys.None, this._ClickMenuFileSettings),
                _CreateSeparator(_MENUFILE_SEPARATOR_RECENT),
                _CreateMenuItem(_MENUFILE_ITEM_EXIT, "E&xit", null, Keys.None, this._ClickMenuFileExit)
                );
            this._MainMenuFile = item;
            this._MainMenu.Items.Add(item);

            // MainMenu.Window
            item = _CreateMenuItem("MenuWindow", "&Okna",
                _CreateMenuItem("WindowArrange", "&Uspořádat",
                    _CreateMenuItem("WindowCascade", "&Kaskáda", this._ClickMenuWindowCascade),
                    _CreateMenuItem("WindowTileVertical", "&Vertikálně", this._ClickMenuWindowTileVertical),
                    _CreateMenuItem("WindowTileHorizontal", "&Horizontálně", this._ClickMenuWindowTileHorizontal),
                    _CreateMenuItem("WindowCloseAll", "&Zavřít vše", this._ClickMenuWindowCloseAll)));
            this._MainMenu.Items.Add(item);
            this._MainMenu.MdiWindowListItem = item;

            // MainMenu.Funkce
            item = _CreateMenuItem("MenuFunction", "&Funkce");
            this._MainMenuFunction = item;
            this._MainMenu.Items.Add(item);

            // MainMenu.Help
            item = _CreateMenuItem("MenuHelp", "&Nápověda",
                _CreateMenuItem("HelpShow", "&Wiki", PicLibrary16.HelpAbout2_FromFile, Keys.F1, this._ClickMenuHelpShow),
                _CreateMenuItem("HelpAbout", "&O programu", this._ClickMenuHelpAbout));
            this._MainMenu.Items.Add(item);

            // Main menu do ToolStripContainer:
            this._TopStripPanel.Controls.Add(this._MainMenu);
        }
        /// <summary>
        /// Vytvoří systémový toolbar, bez přidaných funkcí
        /// </summary>
        private void _InitSystemToolbar()
        {
            this._SystemToolbar = _CreateToolbarStrip("SystemToolbar", DockStyle.None);

            // Vložit do toolbaru položky System.File:
            this._SystemToolbar.Items.AddRange(this._CreateToolItemsSystemFile(false));

            // Vložit do toolbaru obsluhu Undo/Redo:
            this._SystemToolbar.Items.AddRange(this._CreateToolItemsUndoRedo(true));

            this._SystemToolbarRootItemCount = this._SystemToolbar.Items.Count;
            this._TopStripPanel.Controls.Add(this._SystemToolbar);
        }
        private void _InitAfter()
        {
            this.ShowInTaskbar = true;

            this.RePaintBackground();

			MdiClient mdiClient = _FindMdiClient();
			if (mdiClient != null)
			{
				mdiClient.SizeChanged += new EventHandler(_MdiClient_SizeChanged);
				mdiClient.Paint += new PaintEventHandler(_MdiClient_Paint);
			}
			//this.Paint += new PaintEventHandler(_MainAppForm_Paint);
            this.FormClosing += new FormClosingEventHandler(_FormClosing);
            this.KeyDown += new KeyEventHandler(_KeyDown);
            this.KeyPreview = true;
        }
        void _FormClosing(object sender, FormClosingEventArgs e)
        {
            List<TraceDocumentForm> documents = AllTraceDocumentForms;
            if (documents.Count == 0) return;

            // Máme otveřená nějaká okna, radši se zeptáme (podle konfigurace):
            if (!Steward.AppConfig.FormClosingQuery) return;

            string add = ""; // Environment.NewLine + Environment.NewLine + "(Tento dotaz je možno potlačit v konfiguraci)";
            if (Dialog.ShowQuestionYN("Máte otevřené některé projekty. Skutečně je chcete zavřít ?" + add)) return;

            e.Cancel = true;
        }
		void _MdiClient_SizeChanged(object sender, EventArgs e)
		{
			// this.Invalidate();
			MdiClient mdiClient = _FindMdiClient();
			if (mdiClient == null) return;
			mdiClient.Refresh();
		}
		void _MainAppForm_Paint(object sender, PaintEventArgs e)
		{
			this._PaintBackImageCenter(sender, e);
		}
		void _MdiClient_Paint(object sender, PaintEventArgs e)
		{
			this._PaintMdiClientImageCenter(sender, e);
            this._PaintMdiClientLogoHelios(sender, e);
		}
		/// <summary>
		/// Při zobrazení formuláře
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void _MainAppForm_Shown(object sender, EventArgs e)
		{
            this._InitToolStripsLayout();
			this._OpenFileFromArgs();
		}
        /// <summary>
        /// Rozmístí toolstripy při otevírání okna
        /// </summary>
        private void _InitToolStripsLayout()
        {
            this._SystemToolbar.Location = new Point(3, this._MainMenu.Bottom + 3);
            this._FunctionToolbar.Location = new Point(this._SystemToolbar.Right + 5, this._SystemToolbar.Top);

            this._MainMenu.Top = 3;
        }
		void _KeyDown(object sender, KeyEventArgs e)
        {
            // Tady neřeším přímo jednotlivé klávesy, ale předávám argument do metod které si každá může odchytit a vyřešit svoje klávesy.
            if (!e.Handled)
                this._KeyDownUndoRedo(e);
        }
		/// <summary>
		/// Jméno separátoru v menu Soubor, za kterým následuje položka/položky Nedávné soubory
		/// </summary>
		private const string _MENUFILE_SEPARATOR_RECENT = "FileSep3";
		/// <summary>
		/// Jméno položky Konec v menu Soubor
		/// </summary>
		private const string _MENUFILE_ITEM_EXIT = "FileExit";
		#endregion
		#region Menu & Tool construction
		private ToolStripPanel _TopStripPanel;
        private ToolStripPanel _LeftStripPanel;
        private ToolStripPanel _RightStripPanel;
		private MenuStrip _MainMenu;
		/// <summary>
		/// Nabídka menu "Soubor"
		/// </summary>
        private ToolStripMenuItem _MainMenuFile;
        private ToolStripMenuItem _MainMenuFunction;
		private ToolStrip _SystemToolbar;
        private ToolStrip _FunctionToolbar;
        private ToolStrip _SearchToolbar;
		/// <summary>
		/// Počet Items v this._SystemToolbar, které jsou základní = systémové, ty se nemažou
		/// </summary>
		private int _SystemToolbarRootItemCount;
		private MenuStrip _CreateMenuStrip(string name, DockStyle dock, ToolStripGripStyle gripStyle)
		{
			MenuStrip menu = new MenuStrip();
			menu.Name = name;
			menu.Dock = dock;
			menu.GripStyle = gripStyle;
			return menu;
		}
		private ToolStripMenuItem _CreateMenuItem(string name, string text)
		{
			ToolStripMenuItem item = new ToolStripMenuItem();
			item.Name = name;
			item.Text = text;
			return item;
		}
		private ToolStripMenuItem _CreateMenuItem(string name, string text, params ToolStripItem[] dropItems)
		{
			ToolStripMenuItem item = new ToolStripMenuItem();
			item.Name = name;
			item.Text = text;
			item.DropDown.Items.AddRange(dropItems);
			return item;
		}
		private ToolStripMenuItem _CreateMenuItem(string name, string text, EventHandler click)
		{
			ToolStripMenuItem item = new ToolStripMenuItem();
			item.Name = name;
			item.Text = text;
			item.Click += click;
			return item;
		}
		private ToolStripMenuItem _CreateMenuItem(string name, string text, EventHandler click, object tag)
		{
			ToolStripMenuItem item = new ToolStripMenuItem();
			item.Name = name;
			item.Text = text;
			item.Click += click;
			item.Tag = tag;
			return item;
		}
		private ToolStripMenuItem _CreateMenuItem(string name, string text, Image image, Keys shortcutKeys, EventHandler click)
		{
			ToolStripMenuItem item = new ToolStripMenuItem();
			item.Name = name;
			item.Text = text;
			item.Image = image;
			item.ShortcutKeys = shortcutKeys;
			item.Click += click;
			return item;
		}
		private ToolStripMenuItem _CreateMenuItem(string name, string text, Image image, Keys shortcutKeys, EventHandler click, object tag)
		{
			ToolStripMenuItem item = new ToolStripMenuItem();
			item.Name = name;
			item.Text = text;
			item.Image = image;
			item.ShortcutKeys = shortcutKeys;
			item.Click += click;
			item.Tag = tag;
			return item;
		}
		private ToolStrip _CreateToolbarStrip(string name, DockStyle dock, params ToolStripItem[] items)
		{
			ToolStrip tool = new ToolStrip();
			tool.Name = name;
			tool.Dock = dock;
			tool.ImageScalingSize = new Size(22, 22);
            if (items != null && items.Length > 0)
    			tool.Items.AddRange(items);
			return tool;
		}
		private ToolStripButton _CreateToolButton(string name, string text, Image image, string toolTip, EventHandler click)
		{
			ToolStripButton item = new ToolStripButton();
			item.DisplayStyle = ToolStripItemDisplayStyle.Image;
			item.Name = name;
			item.Text = text;
			item.Image = image;
			item.ToolTipText = toolTip;
			item.Size = new System.Drawing.Size(33, 31);
			item.Click += click;
			return item;
		}
		private ToolStripButton _CreateToolButton(string name, string text, Image image, string toolTip, EventHandler click, object tag)
		{
			ToolStripButton item = new ToolStripButton();
			item.DisplayStyle = ToolStripItemDisplayStyle.Image;
			item.Name = name;
			item.Text = text;
			item.Image = image;
			item.ToolTipText = toolTip;
			item.Size = new System.Drawing.Size(33, 31);
            item.Tag = tag;
			item.Click += click;
			return item;
		}
		private ToolStripSeparator _CreateSeparator(string name)
		{
			ToolStripSeparator separator = new ToolStripSeparator();
			separator.Name = name;
			return separator;
		}
		#endregion
        #region Nabídka funkcí
        /// <summary>
        /// Načte seznam globálních funkcí
        /// </summary>
        private void _InitFunctionToolbar()
        {
            this._FunctionToolbar = _CreateToolbarStrip("FunctionToolbar", DockStyle.None);      // = this._SystemToolbar

            // Pro WinXP bez obrázků:
            bool withImages = Environment.OSVersion.Version.Major >= 6;

            // Vložit do toolbaru obsluhu Pointers:
            this._FunctionToolbar.Items.AddRange(this._CreateToolItemsDocPointer(true));

            // Vložit obsluhu Search do toolbaru a do menu funkcí:
            ToolStripItem[] searchToolItems;
            ToolStripItem[] searchMenuItems;
            this._CreateToolItemsSearchProviders(true, false, withImages, out searchToolItems, out searchMenuItems);
            if (searchToolItems != null)
                this._FunctionToolbar.Items.AddRange(searchToolItems);
            if (searchMenuItems != null)
                this._MainMenuFunction.DropDownItems.AddRange(searchMenuItems);

            // Najít globální funkce:
            FunctionMenuSet functionSet = Steward.FunctionGlobalSet;
            if (functionSet != null)
            {
                // Vložit globální funkce do toolbaru:
                this._FunctionToolbar.Items.AddRange(functionSet.CreateToolbarItems(true, withImages, this._FunctionGlobalClick));

                // Vložit globální funkce do menu:
                this._MainMenuFunction.DropDownItems.AddRange(functionSet.CreateMenuItems(true, withImages, this._FunctionGlobalClick));
            }

            // Umístit toolbar funkcí do horního pásu:
            this._TopStripPanel.Controls.Add(this._FunctionToolbar);
            // this._FunctionToolbar.Location = new Point(this._SystemToolbar.Right + 5, this._SystemToolbar.Top);
        }
        /// <summary>
        /// Eventhandler pro událost Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _FunctionGlobalClick(object sender, EventArgs e)
        {
			this._FunctionRun(sender);
        }
		/// <summary>
		/// Zavolá funkci, která je schovaná v senderovi:
		/// (sender as ToolStripItem).Tag as FunctionMenuItem : FunctionMenuElement.RunFunction(...)
		/// </summary>
		/// <param name="sender"></param>
		private void _FunctionRun(object sender)
		{
			FunctionMenuItem functionItem = this._FunctionFindMenuItem(sender);
			if (functionItem == null) return;

			FunctionMenuElement.RunFunction(new FunctionGlobalRunArgs(functionItem, this.ActiveMdiChild));
		}
		/// <summary>
		/// Najde a vrátí funkci, která je schovaná v senderovi:
		/// (sender as ToolStripItem).Tag as FunctionMenuItem
		/// </summary>
		/// <param name="sender"></param>
		private FunctionMenuItem _FunctionFindMenuItem(object sender)
		{
			ToolStripItem item = sender as ToolStripItem;
			if (item == null) return null;
			if (item.Tag == null) return null;

			return item.Tag as FunctionMenuItem;
		}
        #endregion
        #region Undo/Redo buttons
		/// <summary>
		/// Vstupní bod volaný z okna TraceDocumentForm po změně stavu Undo/Redo registr
		/// </summary>
		/// <param name="e"></param>
		internal void OnUndoRedoChanged(EventArgs e)
		{
			this._ToolbarUndoRedoRefresh();
		}
        /// <summary>
        /// Vytvoří a vrátí skupinu položek toolbaru, které zajišťují globální vyhledávání
        /// </summary>
        /// <param name="prependSeparator"></param>
        /// <returns></returns>
        private ToolStripItem[] _CreateToolItemsUndoRedo(bool prependSeparator)
        {
            List<ToolStripItem> items = new List<ToolStripItem>();

            if (prependSeparator)
                items.Add(this._CreateSeparator("GlobalSearchSep"));

			this._ToolbarUndoButton = _CreateToolButton("ToolUndo", "Undo", PicLibrary22.EditUndo1_FromFile, "Vrátí o jeden krok pohyb po dokumentu." + Environment.NewLine + "Backspace, Ctrl+Left.", this._ToolbarUndoClick);
            items.Add(this._ToolbarUndoButton);

			this._ToolbarRedoButton = _CreateToolButton("ToolRedo", "Redo", PicLibrary22.EditRedo1_FromFile, "Provede jeden krok vpřed v pohybu po dokumentu." + Environment.NewLine + "Ctrl+Right.", this._ToolbarRedoClick);
            items.Add(this._ToolbarRedoButton);

            return items.ToArray();
        }
        /// <summary>
        /// Metoda volaná po stisku klávesy.
        /// Zde můžeme detekovat, zda jde o klávesu která řídí Undo/Redo, a pokud ano tak to rovnou provedeme a nastavíme e.Handled = true.
        /// </summary>
        /// <param name="e"></param>
        private void _KeyDownUndoRedo(KeyEventArgs e)
        {
            // Detekce typu akce podle klávesy:
            UndoRedoActionType actionType = UndoRedoCls.DetectKeyEvent(e, true, true, true);

            // Pokud klávesa má vykonat nějakou akci, vykonáme ji:
            if (actionType == UndoRedoActionType.Undo || actionType == UndoRedoActionType.Redo)
            {
                this._ToolbarUndoRedoClick(actionType);
                e.Handled = true;
            }
        }
        private void _ToolbarUndoClick(object sender, EventArgs e)
        {
			this._ToolbarUndoRedoClick(UndoRedoActionType.Undo);
		}
        private void _ToolbarRedoClick(object sender, EventArgs e)
        {
			this._ToolbarUndoRedoClick(UndoRedoActionType.Redo);
		}
		private void _ToolbarUndoRedoClick(UndoRedoActionType actionType)
		{
			TraceDocumentForm docForm = this.TopMostTraceDocument;
			if (docForm == null) return;
			docForm.UndoRedoAction(actionType);
		}
        private void _ToolbarUndoRedoRefresh()
        {
			this._ToolbarUndoRedoRefresh(this.TopMostTraceDocument);
        }
		private void _ToolbarUndoRedoRefresh(TraceDocumentForm traceDocForm)
		{
			bool canUndo = false;
			bool canRedo = false;
			if (traceDocForm != null)
			{
				canUndo = traceDocForm.UndoRedo.CanUndo;
				canRedo = traceDocForm.UndoRedo.CanRedo;
			}
			this._ToolbarUndoButton.Enabled = canUndo;
			this._ToolbarRedoButton.Enabled = canRedo;
		}
		private ToolStripButton _ToolbarUndoButton;
		private ToolStripButton _ToolbarRedoButton;
        #endregion
        #region Search
        /// <summary>
        /// Otevře okno vyhledávání. Pokud jsou předány argumenty, předá je do vyhledávacího panelu (SearchEnginePanel) do metody SearchFill().
        /// </summary>
        public void SearchOpen(string providerName, System.Xml.Linq.XElement presetData)
        {
            if (this._SearchPanel.SearchFill(providerName, presetData))
                this._SearchPanelSetVisible(true);
        }
        /// <summary>
        /// Zajistí zastavení vyhledávání a smazání výsledků hledání.
        /// Volá se po přepnutí dokumentu.
        /// </summary>
        private void _SearchStopClearResult()
        {
            this._SearchPanel.StopSearch();
            this._SearchPanel.ClearResultList();
        }
        /// <summary>
        /// Vytvoří UI prvky pro vyhledávání událostí pro menu a pro toolbar.
        /// </summary>
        /// <param name="prependSeparatorTool"></param>
        /// <param name="prependSeparatorMenu"></param>
        /// <param name="withImages"></param>
        /// <param name="searchToolItems"></param>
        /// <param name="searchMenuItems"></param>
        private void _CreateToolItemsSearchProviders(bool prependSeparatorTool, bool prependSeparatorMenu, bool withImages, out ToolStripItem[] searchToolItems, out ToolStripItem[] searchMenuItems)
        {
            List<ToolStripItem> toolItems = new List<ToolStripItem>();
            List<ToolStripItem> menuItems = new List<ToolStripItem>();

            IEnumerable<ISearchProvider> searchers = Steward.GetServiceObjectList<ISearchProvider>(true);
            if (searchers.Any())
            {
                if (prependSeparatorTool) toolItems.Add(this._CreateSeparator("GlobalSearchSep"));
                if (prependSeparatorMenu) menuItems.Add(this._CreateSeparator("GlobalSearchSep"));

                // ToolItem:
                ToolStripButton btn = new ToolStripButton("Najdi...", PicLibrary22.Documentpreview_FromFile, this._SearchButtonClick);
                btn.ToolTipText = "Umožní vyhledat událost v trace souborech.";
                btn.Width = 75;
                btn.Tag = ToolItemProperties.EnabledDependOnTrace;
                btn.EnabledChanged += new EventHandler(_SearchButtonEnabledChanged);
                toolItems.Add(btn);
                this._ToolComboSearchButton = btn;

                // MenuItem:
                ToolStripMenuItem item = new ToolStripMenuItem("Najdi...", null, this._SearchButtonClick, Keys.Control | Keys.F);
                item.ToolTipText = "Umožní vyhledat událost v trace souborech.";
                item.Tag = ToolItemProperties.EnabledDependOnTrace;
                if (withImages)
                    item.Image = PicLibrary16.Documentpreview_FromFile;
                menuItems.Add(item);
            }
            else
            {
                this._ToolComboSearchButton = null;
            }
            searchToolItems = toolItems.ToArray();
            searchMenuItems = menuItems.ToArray();
        }
        /// <summary>
        /// Po změně Enabled: pokud je false, musí se skrýt toolbar
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _SearchButtonEnabledChanged(object sender, EventArgs e)
        {
            if (!this._ToolComboSearchButton.Enabled && this._ToolComboSearchButton.Checked)
                this._SearchPanelSetVisible(false);
        }
        /// <summary>
		/// Button pro hledání
		/// </summary>
        private ToolStripButton _ToolComboSearchButton;
        /// <summary>
        /// Uživatel klikl na button nového hledání (dialog)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _SearchButtonClick(object sender, EventArgs e)
		{
            this._SearchPanelSetVisible(!this._ToolComboSearchButton.Checked);
        }
        /// <summary>
        /// Uživatel klikl na button Close na vyhledávacím panelu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _SearchPanelHide(object sender, EventArgs e)
        {
            this._SearchPanelSetVisible(false);
        }
        /// <summary>
        /// Nastavit viditelnost vyhledávacího panelu.
        /// </summary>
        /// <param name="isSearch"></param>
        private void _SearchPanelSetVisible(bool isSearch)
        {
            this._ToolComboSearchButton.Checked = isSearch;
            if (this._SearchToolbar.Parent == null)
                this._SearchToolbar.Parent = this._RightStripPanel;
            this._SearchToolbar.Visible = isSearch;
            if (isSearch)
                this._SearchPanel.Focus();
        }
        /// <summary>
        /// Připraví k používání toolstrip obsahující okno hledání
        /// </summary>
        private void _InitSearchToolbar()
        {
            this._SearchToolbar = _CreateToolbarStrip("SearchToolbar", DockStyle.None);   // Toolbar, plave po povrchu některého ToolStripPanelu. V sobě hostuje _SearchToolHost = hostitel Controlů.
            
            this._SearchPanel = new TraceData.SearchEnginePanel();                        // Vlastní vyhledávací panel
            this._SearchPanel.HidePanel += new EventHandler(_SearchPanelHide);
            this._SearchPanel.LayoutArrangedAfter += new EventHandler(_SearchPanel_LayoutArrangedAfter);
            
            this._SearchToolHost = new ToolStripControlHost(this._SearchPanel);           // Hostitel = nosič Controlu v prostředí ToolStripu
            this._SearchToolHost.AutoSize = false;
            
            this._SearchToolbar.Items.Add(this._SearchToolHost);                          // Hostitele do ToolStripu
            this._RightStripPanel.Controls.Add(this._SearchToolbar);                      // ToolStrip do ToolPanelu (do pravého)
            this._RightStripPanel.SizeChanged += new EventHandler(_RightStripPanel_SizeChanged);

            this._SearchToolbar.Visible = false;                                          // Výchozí stav je "Nehledáme"

            this._SearchToolbar.ParentChanged += new EventHandler(_SearchToolbar_ParentChanged);
            this._SearchToolbar.SizeChanged += new EventHandler(_SearchToolbar_SizeChanged);
        }
        /// <summary>
        /// Po změně výšky pravého ToolStripPanelu upravíme výšku _SearchPanel.
        /// Pokud byl _SearchToolbar (nesoucí _SearchPanel) přemístěn jinam, pak: pokud je nahoře, pak to nemá vliv. Pokud je vlevo, pak změna výšky platí pro oba (Left i Right) stejně.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _RightStripPanel_SizeChanged(object sender, EventArgs e)
        {
            this._SetSearchPanelSize();
        }
        /// <summary>
        /// Po dokončení layoutu v Search panelu převezmu jeho Size do Size hostitele (namísto AutoSize = true)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _SearchPanel_LayoutArrangedAfter(object sender, EventArgs e)
        {
            this._SearchToolHost.Size = this._SearchPanel.Size;
        }
        /// <summary>
        /// Po změně velikosti Toolbaru
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _SearchToolbar_SizeChanged(object sender, EventArgs e)
        {
            this._SetSearchPanelSize();
        }
        /// <summary>
        /// Po změně Parenta Toolbaru
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _SearchToolbar_ParentChanged(object sender, EventArgs e)
        {
            if (Object.ReferenceEquals(this._SearchToolbar.Parent, this._TopStripPanel))
                // Nahoru ho nepustím.
                this._SearchToolbar.Parent = null; // this._RightStripPanel;
            else
                this._SetSearchPanelSize();
        }
        /// <summary>
        /// Přizpůsobí výšku _SearchPanel výšce parenta Toolbaru
        /// </summary>
        private void _SetSearchPanelSize()
        {
            if (this._SearchToolbar.Parent != null)
            {
                int height = this._SearchToolbar.Parent.Height;
                this._SearchPanel.HeightDisponible = height - 8;
            }
        }
        /// <summary>
        /// Hostitel vyhledávacího panelu this._SearchPanel.
        /// Panel sám je běžný Widnows.Forms.Control, takový prvek není možno přímo umístit do ToolStrip.Items.
        /// Proto je zde tento hostitel, který v sobě může hostovat Controly, a on sám může být umístěn v ToolStrip.Items.
        /// </summary>
        private ToolStripControlHost _SearchToolHost;
        /// <summary>
        /// Panel, který je hostitelem všech controlů potřebných pro vyhledávání.
        /// Panel je umístěn v hostiteli (ToolStripControlHost), a tento hostitel je pak umístěn v ToolStripu this._SearchToolbar
        /// </summary>
        private Noris.Tools.TraceVisualiser.TraceData.SearchEnginePanel _SearchPanel;
        #endregion
        #region DocPointer (body zájmu)
        /// <summary>
        /// Akceptuje daný pointer = aktivuje graf na jeho pozici
        /// </summary>
        /// <param name="graphPointer"></param>
        internal void DocPointerAccept(TraceVisualiser.Components.IGraphPointer graphPointer)
        {
            this._DocPointerAccept(graphPointer);
        }
        /// <summary>
        /// Vytvoří ToolStripComboBox this._ToolComboPointer, v němž lze zobrazovat Pointery
        /// </summary>
        /// <param name="prependSeparator"></param>
        /// <returns></returns>
        private ToolStripItem[] _CreateToolItemsDocPointer(bool prependSeparator)
        {
            List<ToolStripItem> items = new List<ToolStripItem>();

            if (prependSeparator)
                items.Add(this._CreateSeparator("GlobalSearchSep"));

            // Label:
            ToolStripLabel lbl = new ToolStripLabel("Přejdi na");
            items.Add(lbl);

            // Combo s pointery:
            this._ToolComboPointer = new ToolStripComboBox();
            this._ToolComboPointer.Items.Clear();
            this._ToolComboPointer.AutoSize = false;
            this._ToolComboPointer.Width = 250;
            this._ToolComboPointer.DropDownStyle = ComboBoxStyle.DropDownList;
            this._ToolComboPointer.DropDownWidth = 250;
            this._ToolComboPointer.SelectedIndexChanged += new EventHandler(_DocPointerChanged);
            items.Add(this._ToolComboPointer);

            // Button + DropDown:
            ToolStripSplitButton btn = new ToolStripSplitButton("", PicLibrary22.ListAdd_FromFile);
			btn.ToolTipText = "Uloží aktuální pozici v grafu (čas, otevřené řádky) do nové položky v seznamu pod implicitním jménem." + Environment.NewLine + "Přejmenování položky je možno provést v rozbalovací nabídce.";
            btn.ButtonClick += this._DocPointerAddQuick;
			btn.DropDownItems.Add(new ToolStripButton("Ulož", PicLibrary22.ListAdd_FromFile, this._DocPointerAddFull) { ToolTipText = "Uloží aktuální pozici v grafu (čas, otevřené řádky) do nové položky v seznamu. Umožní položku pojmenovat." });
            btn.DropDownItems.Add(new ToolStripButton("Odstraň", PicLibrary22.ListRemove_FromFile, this._DocPointerDelete) { ToolTipText = "Odebere aktuálně vybranou položku ze seznamu." });
            btn.DropDownItems.Add(new ToolStripButton("Přejmenuj", PicLibrary22.EditRename_FromFile, this._DocPointerRename) { ToolTipText = "Dovolí zadat nové jméno pro vybranou položku." });
            btn.DropDownItems.Add(new ToolStripButton("Aktualizuj", PicLibrary22.EditRedo_FromFile, this._DocPointerReSave) { ToolTipText = "Do vybrané položky v seznamu vepíše aktuální pozici v grafu (přepíše ji)." });
            btn.DropDownButtonWidth = 15;
            btn.Width = 36;
            btn.DropDownDirection = ToolStripDropDownDirection.BelowRight;
            btn.DropDown.DropShadowEnabled = true;
            btn.DropDown.Width = 250;
            items.Add(btn);

            return items.ToArray();
        }
        /// <summary>
        /// ComboBox na Toolbaru: Document.Pointers, který obsahuje nabídky IGraphPointer = odskoky na specifická místa v grafu
        /// </summary>
        private ToolStripComboBox _ToolComboPointer;
        /// <summary>
        /// Do toolbaru do combo _ToolComboPointer vepíše všechny pointery z předaného formuláře
        /// </summary>
        /// <param name="traceDocForm"></param>
        private void _AddDocPointersToToolbar(TraceDocumentForm traceDocForm)
        {
            if (traceDocForm == null)
                _AddDocPointersToCombo(null, null);
            else
                _AddDocPointersToToolbar(traceDocForm.Document, traceDocForm.Document.CurrentDocPointer);
        }
        /// <summary>
        /// Do toolbaru do combo _ToolComboPointer vepíše všechny pointery z předaného dokumentu
        /// </summary>
        /// <param name="document"></param>
        private void _AddDocPointersToToolbar(TraceData.TraceDocument document, object selectItem)
        {
            _AddDocPointersToCombo(document.DocPointers.ToArray(), selectItem);
        }
        /// <summary>
        /// Do toolbaru do combo _ToolComboPointer vepíše všechny pointery z předaného dokumentu
        /// </summary>
        /// <param name="traceDocument"></param>
        private void _AddDocPointersToCombo(object[] pointers, object selectItem)
        {
            this._DocPointerChangeDisabled = true;
            
            this._ToolComboPointer.Items.Clear();
            if (pointers != null)
            {
                foreach (object pointer in pointers)
                {
                    if (pointer != null)
                        this._ToolComboPointer.Items.Add(pointer);
                }
            }
            this._ToolComboPointer.SelectedItem = selectItem;

            this._DocPointerChangeDisabled = false;
        }
        /// <summary>
        /// Eventhandler po změně pointeru ve výběru v ComboBoxu.
        /// Zde se čte hodnota _DocPointerChangeDisabled, a pokud je true pak se na změnu nereaguje.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _DocPointerChanged(object sender, EventArgs args)
        {
            if (_DocPointerChangeDisabled) return;
            this._DocPointerAccept(_DocPointerGetSelectedGraphPointer());
            this._FocusToGraph();
        }
        /// <summary>
        /// Akceptuje daný GraphPointer = promítne jeho vlastnosti do aktuálního grafu
        /// </summary>
        private void _DocPointerAccept(TraceVisualiser.Components.IGraphPointer graphPointer)
        {
            if (graphPointer == null) return;

            TraceDocumentForm traceDocForm = this.TopMostTraceDocument;
            if (traceDocForm == null) return;
            if (traceDocForm.Graph == null) return;

            // Uložím si pointer do dokumentu, při změně okna se do toolbaru přenese právě tato hodnota jak preselect:
            if (traceDocForm.Document != null)
                traceDocForm.Document.CurrentDocPointer = graphPointer;

            traceDocForm.Graph.GraphPointerAccept(graphPointer);
        }
        /// <summary>
        /// Příznak, že se má ignorovat event this._ToolComboPointer.SelectedIndexChanged (v metodě this._DocPointerChanged()).
        /// Nastavuje se na true při načítání dat do comba, aby bylo možno potlačit aktivaci pointeru (má reagovat pouze na výběr uživatele, ne na vložení hodnoty programem - napřílad po přidání nové položky)
        /// </summary>
        private bool _DocPointerChangeDisabled;
        /// <summary>
        /// Přidá novou položku GraphPointer, rychle = bez uživatelského pojmenování
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
		private void _DocPointerAddQuick(object sender, EventArgs args)
		{
			this._DocPointerAdd(false);
		}
		/// <summary>
		/// Přidá novou položku GraphPointer, plně = včetně uživatelského pojmenování
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="args"></param>
		private void _DocPointerAddFull(object sender, EventArgs args)
		{
			this._DocPointerAdd(true);
		}
        /// <summary>
        /// Přidá novou položku GraphPointer
        /// </summary>
		/// <param name="withName">Včetně zadání jména?</param>
        private void _DocPointerAdd(bool withName)
        {
            TraceDocumentForm traceDocForm = this.TopMostTraceDocument;
            if (traceDocForm == null) return;
            if (traceDocForm.Graph == null) return;
            if (traceDocForm.Document == null) return;

			// TraceDocument vytvoří a vrátí nový objekt IGraphPointer, současně si jej vloží do svého seznamu
			TraceVisualiser.Components.IGraphPointer graphPointer = traceDocForm.Document.GetNewDocPointer(withName);
            if (graphPointer != null)
            {
                traceDocForm.Graph.GraphPointerFill(graphPointer);                   // Graf do objektu vepíše informace o pointeru, a protože jde o class, tak se tyto informace ukládají do téhož objektu, který je uložen v TraceDocument.
                this._AddDocPointersToToolbar(traceDocForm.Document, graphPointer);  // ReFill combo, ale neprovádí se event _DocPointerChanged()
                traceDocForm.Document.SaveAuto();
            }

            this._FocusToGraph();
        }
        /// <summary>
        /// Přejmenuje vybranou položku GraphPointeru
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _DocPointerRename(object sender, EventArgs args)
        {
			TraceDocumentForm traceDocForm = this.TopMostTraceDocument;
			if (traceDocForm == null) return;
			if (traceDocForm.Graph == null) return;
			if (traceDocForm.Document == null) return;

			TraceVisualiser.Components.IGraphPointer graphPointer = _DocPointerGetSelectedGraphPointer();
			if (graphPointer == null) return;

            if (traceDocForm.Document.RenameDocPointer(graphPointer))
            {
                this._AddDocPointersToToolbar(traceDocForm.Document, graphPointer);
                traceDocForm.Document.SaveAuto();
            }

			this._FocusToGraph();
		}
        /// <summary>
        /// Zajistí smazání aktuálně vybrané pozice GraphPointeru v aktuálním okně
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _DocPointerDelete(object sender, EventArgs args)
        {
            TraceDocumentForm traceDocForm = this.TopMostTraceDocument;
            if (traceDocForm == null) return;
            if (traceDocForm.Graph == null) return;
            if (traceDocForm.Document == null) return;

            TraceVisualiser.Components.IGraphPointer graphPointer = _DocPointerGetSelectedGraphPointer();
            if (graphPointer == null) return;

            if (traceDocForm.Document.DeleteDocPointer(graphPointer))
            {
                this._AddDocPointersToToolbar(traceDocForm.Document, null);
                traceDocForm.Document.SaveAuto();
            }

            this._FocusToGraph();
        }
        /// <summary>
        /// Zajistí znovu uložení dat do aktuálně vybrané pozice
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void _DocPointerReSave(object sender, EventArgs args)
        {
            TraceDocumentForm traceDocForm = this.TopMostTraceDocument;
            if (traceDocForm == null) return;
            if (traceDocForm.Graph == null) return;

            TraceVisualiser.Components.IGraphPointer graphPointer = _DocPointerGetSelectedGraphPointer();
            if (graphPointer == null) return;

            traceDocForm.Graph.GraphPointerFill(graphPointer);            // Graf do objektu vepíše informace o pointeru, a protože jde o class, tak se tyto informace ukládají do téhož objektu, který je uložen v TraceDocument.
            traceDocForm.Document.SaveAuto();

            this._FocusToGraph();
        }
        /// <summary>
        /// Odešle focus (kurzor) do grafu aktuálního okna
        /// </summary>
        private void _FocusToGraph()
        {
            TraceDocumentForm traceDocForm = this.TopMostTraceDocument;
            if (traceDocForm == null) return;
            if (traceDocForm.Graph == null) return;
            traceDocForm.Graph.Focus();
        }
        /// <summary>
        /// Metoda vrátí objekt IGraphPointer, který je právě nyní vybrán v this._ToolComboPointer.
        /// Pokud není vybrán žádný objekt, nebo vybraný objekt není IGraphPointer, vrací null.
        /// </summary>
        /// <returns></returns>
        private TraceVisualiser.Components.IGraphPointer _DocPointerGetSelectedGraphPointer()
        {
            object selected = this._ToolComboPointer.SelectedItem;
            if (selected == null) return null;
            return selected as TraceVisualiser.Components.IGraphPointer;
        }
        #endregion
        #region Události formu - tvorba systémových položek, obsluha menu
        /// <summary>
        /// Vytvoří a vrátí skupinu položek toolbaru, které představuje systémové nástroje File
        /// </summary>
        /// <param name="prependSeparator"></param>
        /// <returns></returns>
        private ToolStripItem[] _CreateToolItemsSystemFile(bool prependSeparator)
        {
            List<ToolStripItem> items = new List<ToolStripItem>();

            if (prependSeparator)
                items.Add(this._CreateSeparator("GlobalSearchSep"));

            items.Add(_CreateToolButton("ToolNew", "Nový", PicLibrary22.Documentnew5_FromFile, "Založí nový projekt", this._ClickMenuFileNew));
            items.Add(_CreateToolButton("ToolOpen", "Otevře", PicLibrary22.Documentopen4_FromFile, "Otevře existující projekt", this._ClickMenuFileOpen));
            items.Add(_CreateToolButton("ToolSave", "Uloží", PicLibrary22.Documentsave3_FromFile, "Uloží otevřený projekt", this._ClickMenuFileSave, ToolItemProperties.EnabledDependOnTrace));
            items.Add(_CreateToolButton("ToolSaveAs", "Uloží jako", PicLibrary22.Documentsaveall_FromFile, "Uloží otevřený projekt do nového projektu", this._ClickMenuFileSaveAs, ToolItemProperties.EnabledDependOnTrace));
            items.Add(_CreateSeparator("ToolSep1"));
            items.Add(_CreateToolButton("ToolProperties", "Vlastnosti", PicLibrary22.Documentproperties3_FromFile, "Nastaví vlastnosti projektu", this._ClickMenuFileProperties, ToolItemProperties.EnabledDependOnTrace));
            items.Add(_CreateToolButton("ToolAuditlog", "Auditlog", PicLibrary22.MailMarkImportant2_FromFile, "Zobrazí auditlog s přehledem problémů", this._ClickMenuFileAuditlog, ToolItemProperties.EnabledDependOnTrace));

            return items.ToArray();
        }
        private void _ClickMenuFileNew(object sender, EventArgs e)
        {
			this._DocumentNew();
		}
        private void _ClickMenuFileOpen(object sender, EventArgs e)
        {
			string file = TraceData.TraceDocument.OpenFileDialog();
			if (!String.IsNullOrEmpty(file))
				this._DocumentOpen(file);
		}
        private void _ClickMenuFileProperties(object sender, EventArgs e)
        {
			TraceDocumentForm form = this.ActiveDocumentForm;
			if (form == null) return;
			form.Document.ShowPropertiesFormDialog();
		}
        private void _ClickMenuFileAuditlog(object sender, EventArgs e)
        {
			TraceDocumentForm form = this.ActiveDocumentForm;
			if (form == null) return;
			form.Document.ShowAuditlogFormDialog();
		}
        private void _ClickMenuFileSave(object sender, EventArgs e)
        {
			TraceDocumentForm form = this.ActiveDocumentForm;
			if (form == null) return;
			if (String.IsNullOrEmpty(form.Document.ProjectFile))
				this._DocumentSaveAs(form.Document, null);
			else
				form.Document.Save();
		}
        private void _ClickMenuFileSaveAs(object sender, EventArgs e)
		{
			TraceDocumentForm form = this.ActiveDocumentForm;
			if (form == null) return;
			this._DocumentSaveAs(form.Document, form.Document.ProjectFile);
		}
		private void _ClickMenuRecentFile(object sender, EventArgs e)
        {
			if (sender is ToolStripMenuItem)
			{
				ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
				this._DocumentOpen(menuItem.Tag as string);
			}
		}
        private void _ClickMenuFileSettings(object sender, EventArgs e)
        {
			this._SettingsShowDialog();
		}
        private void _ClickMenuFileExit(object sender, EventArgs e)
        {
            this.Close();
        }
        private void _ClickMenuWindowCascade(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.Cascade);
        }
        private void _ClickMenuWindowTileVertical(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileVertical);
        }
        private void _ClickMenuWindowTileHorizontal(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileHorizontal);
        }
        private void _ClickMenuWindowCloseAll(object sender, EventArgs e)
        {
            foreach (Form childForm in MdiChildren)
            {
                childForm.Close();
            }
        }
        private void _ClickMenuHelpShow(object sender, EventArgs e)
        {
            string url = @"https://forum.helios.eu/green/doc/cs/index.php?title=Trace_Visualiser_-_spr%C3%A1vce";
            Steward.RunProcess(url);
        }
        private void _ClickMenuHelpAbout(object sender, EventArgs e)
        {
            using (AboutForm form = new AboutForm())
            {
                form.ShowDialog(Steward.MainForm);
            }
        }
		/// <summary>
		/// Obsahuje (najde) aktuálně aktivní MDI child form, pokud to je grafický dokument
		/// </summary>
		private TraceDocumentForm ActiveDocumentForm
		{
			get
			{
				Form activeMdiChild = this.ActiveMdiChild;
				if (activeMdiChild == null) return null;
				if (activeMdiChild is TraceDocumentForm)
					return activeMdiChild as TraceDocumentForm;
				return null;
			}
		}
		/// <summary>
		/// Obsahuje (vždy vygeneruje aktuální) seznam všech oken typu TraceDocumentForm, která jsou v tuto chvíli v projektu otevřená.
		/// Okna bere z evidence WinForm
		/// </summary>
		private List<TraceDocumentForm> AllTraceDocumentForms
		{
			get
			{
				List<TraceDocumentForm> forms = new List<TraceDocumentForm>();
				foreach (var form in this.MdiChildren)
				{
					if (form is TraceDocumentForm)
						forms.Add(form as TraceDocumentForm);
				}
				return forms;
			}
		}
        #endregion
        #region Otevírání trace dokumentů při startu aplikace
        /// <summary>
        /// Příznak (true), zda je třeba otevřít soubory předané jako argumenty aplikace.
        /// Na true se nastavuje při inicializaci, a na false se shodí v metodě, která dokumenty otevírá.
        /// Zajistí se tím to, že se soubory otevřou skutečně jen poprve.
        /// </summary>
        private bool _OpenFileOnFirstShown;
        /// <summary>
        /// Zajistí prohledání parametrů aplikace (args), zda nebyl předán nějaký soubor (hegtv / csv), a případně zajistí jeho otevření
        /// </summary>
        private void _OpenFileFromArgs()
        {
            /*
            string args = "";
            List<KeyValuePair<string, string>> pl = Steward.ParamList;
            foreach (KeyValuePair<string, string> p in pl)
            {
                string l = "Key={" + p.Key.ToStringNull() + "}      Value={" + p.Value.ToStringNull() + "}" + Environment.NewLine;
                args += l;
            }
            Dialog.ShowInfo(args);
            */


            if (!this._OpenFileOnFirstShown) return;

            // Pokud je předán parametr, který má Key = soubor a Value = empty, anebo Key = /open a Value = soubor, pak takový soubor otevřu:
            List<KeyValuePair<string, string>> param = Steward.ParamList;
            foreach (KeyValuePair<string, string> item in param)
            {
                string fileName;
                if (this._ParamContainFile(item, out fileName))
                {
                    if (this._ParamOpenFile(fileName))
                        break;
                }
            }
            this._OpenFileOnFirstShown = false;
        }
        /// <summary>
        /// Určí, zda daný pár parametru (Key,Value) se odkazuje na vstupní soubor
        /// </summary>
        /// <param name="item"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private bool _ParamContainFile(KeyValuePair<string, string> item, out string fileName)
        {
            fileName = null;
            if (!String.IsNullOrEmpty(item.Key) && String.IsNullOrEmpty(item.Value) && System.IO.File.Exists(item.Key))
            {
                fileName = item.Key;
                return true;
            }
            if (_ParamKeyFile(item, "open", false) || _ParamKeyFile(item, "/tap", true))
            {
                fileName = item.Value;
                return true;
            }
            return false;
        }
        /// <summary>
        /// Vrátí true, pokud daný parametr (pár Key,Value) obsahuje daný klíč a existující soubor
        /// </summary>
        /// <param name="item">Parametr (pár Key,Value)</param>
        /// <param name="find">Daný klíč (porovnává se ToLower())</param>
        /// <param name="startsWith">Klíč musí být StartsWith (true) anebo Contains (false)</param>
        /// <returns></returns>
        private bool _ParamKeyFile(KeyValuePair<string, string> item, string find, bool startsWith)
        {
            if (String.IsNullOrEmpty(item.Key)) return false;
            if (startsWith)
            {
                if (!item.Key.ToLower().StartsWith(find.ToLower()))
                    return false;
            }
            else
            {
                if (!item.Key.ToLower().Contains(find.ToLower()))
                    return false;
            }


                if (String.IsNullOrEmpty(item.Value)) return false;
            return System.IO.File.Exists(item.Value);
        }
        /// <summary>
        /// Pokusí se otevřít soubor
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private bool _ParamOpenFile(string fileName)
        {
            if (String.IsNullOrEmpty(fileName)) return false;
            if (!System.IO.File.Exists(fileName)) return false;
            string ext = System.IO.Path.GetExtension(fileName).ToLower();
            switch (ext)
            {
                case ".csv":
                    this._DocumentNewForCsv(fileName);
                    return true;
                case ".hegta":
                    this._DocumentNewForHegTa(fileName);
                    return true;
                case ".hegtv":
                    this._DocumentNewForHegTv(fileName);
                    return true;
            }
            return false;
        }
        /// <summary>
        /// Vytvoří nový projekt pro jeden soubor CSV
        /// </summary>
        /// <param name="fileName"></param>
        private void _DocumentNewForCsv(string fileName)
        {
            TraceData.TraceDocument document = TraceData.TraceDocument.CreateForCsvFile(fileName);
            document.ShowTraceDataForm(this);
        }
        /// <summary>
        /// Vytvoří nový projekt pro jeden soubor HEGTA
        /// </summary>
        /// <param name="fileName"></param>
        private void _DocumentNewForHegTa(string fileName)
        {
            TraceData.TraceDocument document = TraceData.TraceDocument.CreateForHegTAFile(fileName);
            document.ShowTraceDataForm(this);
        }
        /// <summary>
        /// Vytvoří nový projekt pro jeden soubor HEGTV
        /// </summary>
        /// <param name="fileName"></param>
        private void _DocumentNewForHegTv(string fileName)
        {
            TraceData.TraceDocument document = TraceData.TraceDocument.CreateForHegTVFile(fileName);
            document.ShowTraceDataForm(this);
        }
        #endregion
        #region Registr topmost okna, event při změně okna
        /// <summary>
        /// Reference na okno typu TraceDocumentForm, které je navrchu.
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public TraceDocumentForm TopMostTraceDocument { get; private set; }
        /// <summary>
        /// Event při změně aktivního MDI okna
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _MdiChildActivate(object sender, EventArgs e)
        {
            Form child = this.ActiveMdiChild;
            if (child == null)
            {
                this.TopMostTraceDocument = null;
                this.TraceDocumentActivated(null);
            }
            else if (child is TraceDocumentForm)
            {
                this.TopMostTraceDocument = child as TraceDocumentForm;
                this.TraceDocumentActivated(this.TopMostTraceDocument);
            }
        }
        #endregion
        #region Reakce okna na změnu dokumentu (otevření projektu, přepnutí aktivního projektu, zavření okna) - vliv na stav a obsah Toolbaru
        /// <summary>
        /// Metoda volaná po aktivaci / deaktivaci MDI child okna.
        /// Okno může reagovat (enabled / disabled na položky menu+toolbaru, výměna obsah toolbaru, atd)
        /// </summary>
        /// <param name="traceDocForm"></param>
        protected void TraceDocumentActivated(TraceDocumentForm traceDocForm)
        {
			this._ToolbarUndoRedoRefresh(traceDocForm);
			this._AddDocPointersToToolbar(traceDocForm);
			this._FunctionByFormEnabled(traceDocForm != null);
            this._SearchStopClearResult();
            this._AuditlogByDocEnabled(traceDocForm);
        }
        /// <summary>
        /// Nastaví Enabled na toolitem Auditlog, podle obsahu auditlogu daného dokumentu
        /// </summary>
        /// <param name="traceDocForm"></param>
        private void _AuditlogByDocEnabled(TraceDocumentForm traceDocForm)
        {
            bool auditEnabled = false;
            if (traceDocForm != null && traceDocForm.Document.Auditlog.ContainWarningOrError)
                auditEnabled = true;

            IEnumerable<ToolStripItem> items = _GetUiItems(i => (i.Name == "FileAuditlog" || i.Name == "ToolAuditlog"));
            foreach (ToolStripItem item in items)
                item.Enabled = auditEnabled;
        }
        /// <summary>
        /// Metoda, která nastaví Enabled pro ty položky menu funkcí a toolbar, které jsou závislé na aktivním okně.
        /// </summary>
        /// <param name="formActive"></param>
        private void _FunctionByFormEnabled(bool formActive)
        {
            // Soupis prvků UI, které jsou závislé na formuláři TraceDokument (detekuje metoda _FunctionItemEnabledDependOnTraceForm()):
            IEnumerable<ToolStripItem> items = _GetUiItems(i => _FunctionItemEnabledDependOnTraceForm(i));
            foreach (ToolStripItem item in items)
                item.Enabled = formActive;
        }
        /// <summary>
        /// Metoda zjistí, zda položka menu má svoje Enabled mít závislé na aktivním formuláři typu TraceDocumentForm
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private bool _FunctionItemEnabledDependOnTraceForm(ToolStripItem item)
        {
            if (item == null) return false;
            object tag = item.Tag;
            if (tag == null) return false;

            if (tag is ToolItemProperties)
            {
                ToolItemProperties properties = (ToolItemProperties)tag;
                return ((properties & ToolItemProperties.EnabledDependOnTrace) > 0);
            }
            if (tag is FunctionMenuElement)
            {
                FunctionMenuElement menuElement = tag as FunctionMenuElement;
                return ((menuElement.ItemProperties & ToolItemProperties.EnabledDependOnTrace) > 0);
            }

            return false;
        }
        /// <summary>
        /// Vrátí seznam prvků UI, které odpovídají danému filtru
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        private IEnumerable<ToolStripItem> _GetUiItems(Func<ToolStripItem, bool> where)
        {
            List<ToolStripItem> items = new List<ToolStripItem>();      // Souhrn položek menu + toolbaru, které mohu být závislé na otevřeném dokumentu
            items.AddRange(this._GetListFromCollection(this._MainMenuFile.DropDownItems));       // Menu Soubor
            items.AddRange(this._GetListFromCollection(this._MainMenuFunction.DropDownItems));   // Menu Funkce
            items.AddRange(this._GetListFromCollection(this._SystemToolbar.Items));              // System Toolbar
            items.AddRange(this._GetListFromCollection(this._FunctionToolbar.Items));            // Functions Toolbar
            items.AddRange(this._GetListFromCollection(this._SearchToolbar.Items));              // Search Toolbar
            return items.Where(where);
        }
        private ToolStripItem[] _GetListFromCollection(ToolStripItemCollection collection)
        {
            ToolStripItem[] result = new ToolStripItem[collection.Count];
            collection.CopyTo(result, 0);
            return result;
        }
        #endregion
        #region Práce s projektem
		/// <summary>
		/// Založí nový projekt
		/// </summary>
        private void _DocumentNew()
		{
			TraceData.TraceDocument document = new TraceData.TraceDocument(true);
			DialogResult result = document.ShowPropertiesFormDialog();
			if (result == System.Windows.Forms.DialogResult.OK)
			{
				this.LastProjectAdd(document.ProjectFile);
				document.ShowTraceDataForm(this);
			}
		}
		/// <summary>
		/// Otevře projekt
		/// </summary>
		/// <param name="file"></param>
		private void _DocumentOpen(string file)
		{
			if (String.IsNullOrEmpty(file)) return;
			if (!System.IO.File.Exists(file))
			{	// Pokud soubor neexistuje, pak jej (případně) odebere z RecentProjectList a skončí:
				this.LastProjectRemove(file);
				return;
			}
			this.LastProjectAdd(file);

			TraceData.TraceDocument document = new TraceData.TraceDocument(file);
			document.ShowTraceDataForm(this);
		}
		/// <summary>
		/// Uloží projekt do souboru, který si určí uživatel.
		/// </summary>
		/// <param name="document"></param>
		/// <param name="oldFileName"></param>
		private void _DocumentSaveAs(TraceData.TraceDocument document, string oldFileName)
		{
			string file = TraceData.TraceDocument.SaveAsFileDialog(oldFileName);
			if (String.IsNullOrEmpty(file))
				return;

			this.LastProjectAdd(file);
			document.SaveAs(file);
		}
		#endregion
        #region Last Project List (recent files)
        /// <summary>
        /// Přidá dané jméno souboru (projekt) do paměti RecentFiles, zajistí refresh menu Soubor
        /// </summary>
        /// <param name="projectFile"></param>
        public void LastProjectAdd(string projectFile)
        {
            if (String.IsNullOrEmpty(projectFile)) return;
            bool isChange = Steward.AppConfig.LastProjectsAdd(projectFile);
            if (isChange)
                this.LastProjectInsertIntoMenu();
        }
        /// <summary>
        /// Odebere daný soubor z paměti RecentFiles, zajistí refresh menu Soubor
        /// </summary>
        /// <param name="projectFile"></param>
        public void LastProjectRemove(string projectFile)
        {
            if (String.IsNullOrEmpty(projectFile)) return;
            bool isChange = Steward.AppConfig.LastProjectRemove(projectFile);
            if (isChange)
                this.LastProjectInsertIntoMenu();
        }
        /// <summary>
        /// Do menu "Soubor" vloží položky RecentFiles
        /// </summary>
        public void LastProjectInsertIntoMenu()
        {
            // Položky Recent se mají vkládat do menu this._MainMenuFile, za položku s názvem "FileSep3", před položku "FileExit":
            ToolStripMenuItem menuFile = this._MainMenuFile;

            // Odebrat všechny položky za položkou "FileSep3", před položkou "FileExit":
			int idxRecent = menuFile.DropDownItems.IndexOfKey(_MENUFILE_SEPARATOR_RECENT);   // Na tomto indexu je separátor, za nímž by měly být položky RecentFile...
            if (idxRecent >= 0)
            {
                idxRecent++;
                while (idxRecent < menuFile.DropDownItems.Count)
                {
                    string name = menuFile.DropDownItems[idxRecent].Name;
					if (name == _MENUFILE_ITEM_EXIT) break;            // Položka menu "Konec": tu (a vše další) tam necháme...
                    menuFile.DropDownItems.RemoveAt(idxRecent);        // Ostatní položky tam nemají co dělat, jde o RecentFiles nebo "FileSepRecent"
                }
            }
            else
                idxRecent = menuFile.DropDownItems.Count;

            // Přidat RecentFiles na pozici idxRecent++:
            List<string> recentFiles = Steward.AppConfig.LastProjects;
            if (recentFiles != null && recentFiles.Count > 0)
            {
				// Podle počtu daného v konfiguraci:
				int configCount = Steward.AppConfig.LastProjectsCount;
				if (configCount >= 1 && configCount <= 7)
				{	// Pokud je nakonfigurováno méně než 8 položek, zobrazují se přímo v menu Soubor:
					LastProjectInsertIntoMenu(menuFile.DropDownItems, recentFiles, ref idxRecent);
					menuFile.DropDownItems.Insert(idxRecent++, _CreateSeparator("FileSepRecent"));
				}
				else if (configCount >= 8)
				{	// Pokud je zadáno 8 a více položek, budou v odděleném submenu:
					ToolStripMenuItem menuItem = _CreateMenuItem("RecentFiles", "Nedávné soubory");
					menuFile.DropDownItems.Insert(idxRecent++, menuItem);
					int subIdxRecent = 0;
					LastProjectInsertIntoMenu(menuItem.DropDownItems, recentFiles, ref subIdxRecent);
					menuFile.DropDownItems.Insert(idxRecent++, _CreateSeparator("FileSepRecent"));
				}
            }
        }
		/// <summary>
		/// Do daného submenu vloží dané soubory na pozici počínaje daným indexem
		/// </summary>
		/// <param name="subMenuCollection"></param>
		/// <param name="recentFiles"></param>
		/// <param name="idxRecent"></param>
		private void LastProjectInsertIntoMenu(ToolStripItemCollection subMenuCollection, List<string> recentFiles , ref int idxRecent)
		{
			for (int f = 0; f < recentFiles.Count; f++)
			{
				string recentFile = recentFiles[f];
				System.IO.FileInfo rfi = new System.IO.FileInfo(recentFile);
				string menuText = System.IO.Path.Combine(rfi.Directory.Name, System.IO.Path.GetFileNameWithoutExtension(rfi.Name));
				if (menuText.Length > 40)
					menuText = System.IO.Path.GetFileNameWithoutExtension(recentFile);

				if (f <= 8)
					menuText = "&" + (f + 1).ToString() + " " + menuText;

				ToolStripMenuItem menuItem = _CreateMenuItem("RecentFile" + f.ToString(), menuText, this._ClickMenuRecentFile, (object)recentFile);
				menuItem.ToolTipText = recentFile;

				if (idxRecent >= subMenuCollection.Count)
				{
					subMenuCollection.Add(menuItem);
					idxRecent++;
				}
				else
				{
					subMenuCollection.Insert(idxRecent++, menuItem);
				}
			}
		}
        #endregion
		#region Další funkce hlavího okna
		/// <summary>
		/// Zobrazení konfigurace aplikace
		/// </summary>
		private void _SettingsShowDialog()
		{
            Steward.OpenDialogFormInTryCatch(typeof(SettingsForm), "V okně konfigurace došlo k chybě: %0", form => ((SettingsForm)form).SettingsChanged += new EventHandler(_SettingsChanged));
		}
		/// <summary>
		/// Handler volaný po změně konfigurace v okně: 
		/// je třeba konfiguraci uložit, a překreslit okna všech dokumetů (vliv změny barev)
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void _SettingsChanged(object sender, EventArgs e)
		{
            this.RePaintBackground();
			this.RefreshAllTraceForms();
			this.LastProjectInsertIntoMenu();
		}
        /// <summary>
        /// Metoda zajistí nastavení vlastností MainForm.Background podle konfigurace (
        /// </summary>
        public void RePaintBackground()
        {
            Config config = Steward.AppConfig;

            Color backColor = SystemColors.AppWorkspace;         // SystemColors.AppWorkspace;
            ImageLayout imageLayout = ImageLayout.None;
            Image imageTile = null;
			this._ImageCenter = null;
            Config.MainBackgroundMode backMode = (Steward.IsStartedFromTA ? Config.MainBackgroundMode.StandardTraceAnalyser : config.BackgroundMode);
            switch (backMode)
            {
                case Config.MainBackgroundMode.None:
                case Config.MainBackgroundMode.StandardWindows:
                    break;
                case Config.MainBackgroundMode.StandardTraceAnalyser:
                    backColor = Steward.TraceAnalyserBackColor;            // Požadavek JD + DCH z 2012-02-14
                    break;
                case Config.MainBackgroundMode.FullColor:
                    backColor = config.BackgroundColor;
                    break;
                case Config.MainBackgroundMode.ImageTile:
                    backColor = config.BackgroundColor;
                    imageTile = _GetImageFromFile(config.BackgroundImageFile);
                    if (imageTile != null)
                        imageLayout = ImageLayout.Tile;
                    break;
                case Config.MainBackgroundMode.ImageCenter:
                    backColor = config.BackgroundColor;
					this._ImageCenter = _GetImageFromFile(config.BackgroundImageFile);     // Vykreslení zajišťuje událost Paint
                    break;
                case Config.MainBackgroundMode.InternalTile:
                    backColor = config.BackgroundColor;
                    // backImage = Lcs.TraceVisualiser.Pics.PicLibrary.Bgr1_FromFile;         // To je tak jemná mřížka, že ji nestíhá monitor (plocha bliká)
                    // backImage = Lcs.TraceVisualiser.Pics.PicLibrary.Bgr2_FromFile;         // Relativně OK
                    // backImage = Lcs.TraceVisualiser.Pics.PicLibrary.Bgr3_FromFile;         // To je psycho obrázek, z toho jdou oči šejdrem a motá se hlava !!!
                    imageTile = TraceVisualiser.Pics.PicLibrary.Bgr4_FromFile;
                    if (imageTile != null)
                        imageLayout = ImageLayout.Tile;
                    break;
            }
			MdiClient mdiClient = _FindMdiClient();
			if (backColor.A == 255)               // BackColor nesmí být průhledné!
			{
				this.BackColor = backColor;
				if (mdiClient != null)
					mdiClient.BackColor = backColor;
			}

            this.BackgroundImageLayout = imageLayout;
			this.BackgroundImage = imageTile;
			if (mdiClient != null)
				mdiClient.BackgroundImage = imageTile;
        }
		private Image _ImageCenter;
		void _PaintMdiClientImageCenter(object sender, PaintEventArgs e)
		{
			if (this._ImageCenter == null) return;
			MdiClient mdiClient = _FindMdiClient();
			if (mdiClient == null) return;

			Rectangle area = mdiClient.ClientRectangle;
			this._PaintImageCenter(e.Graphics, area, this._ImageCenter);
		}
        private void _PaintMdiClientLogoHelios(object sender, PaintEventArgs e)
        {
            Image logo = Noris.Tools.TraceVisualiser.Pics.PicLibrary.HeliosLogo_Cached;
            if (logo == null) return;
            MdiClient mdiClient = _FindMdiClient();
            if (mdiClient == null) return;
            Rectangle area = mdiClient.ClientRectangle;
            Rectangle imag = new Rectangle(area.Width - logo.Width - 6, area.Height - logo.Height - 6, logo.Width, logo.Height);
            e.Graphics.DrawImage(logo, imag);
        }
        void _PaintBackImageCenter(object sender, PaintEventArgs e)
		{
			if (this._ImageCenter == null) return;
			Rectangle area = this.ClientRectangle;
			this._PaintImageCenter(e.Graphics, area, this._ImageCenter);
		}

		private void _PaintImageCenter(Graphics graphics, Rectangle area, Image image)
		{
			SizeF sizeR = image.Size;
			float cfcH = (float)area.Height / sizeR.Height;
			float cfcW = (float)area.Width / sizeR.Width;
			float cfc = Math.Min(cfcH, cfcW);
			SizeF sizeI = new SizeF(cfc * sizeR.Width, cfc * sizeR.Height);
			Rectangle areaI = Rectangle.Round(GetCenterArea(area, sizeI));

			graphics.Clear(this.BackColor);
			graphics.DrawImage(image, areaI);
		}
		/// <summary>
		/// Vrátí RectangleF, který má shodný střed jako daný RectangleF, a má danou velikost.
		/// </summary>
		/// <param name="outerArea"></param>
		/// <param name="size"></param>
		/// <returns></returns>
		private static System.Drawing.RectangleF GetCenterArea(System.Drawing.RectangleF outerArea, System.Drawing.SizeF size)
		{
			PointF center = new System.Drawing.PointF(outerArea.X + outerArea.Width / 2F, outerArea.Y + outerArea.Height / 2F);
			RectangleF centerArea = new System.Drawing.RectangleF(center.X - size.Width / 2F, center.Y - size.Height / 2F, size.Width, size.Height);
			return centerArea;
		}
		MdiClient _FindMdiClient()
		{
			foreach (Control control in this.Controls)
			{
				if (control is MdiClient)
				{
					return (control as MdiClient);
				}
			}
			return null;
		}
		/// <summary>
        /// Vrátí Image načtený ze souboru.
        /// Testuje, že je jméno zadané, soubor existuje.
        /// Pokud Image nelze načíst, vrátí null (i chybu utopí).
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private Image _GetImageFromFile(string fileName)
        {
            if (String.IsNullOrEmpty(fileName)) return null;
            if (!System.IO.File.Exists(fileName)) return null;
            try
            {
                return Image.FromFile(fileName);
            }
            catch { }
            return null;
        }
		/// <summary>
		/// Zajistí zavolání Refresh na všechny formuláře s TraceDokumenty
		/// </summary>
		public void RefreshAllTraceForms()
		{
			foreach (TraceDocumentForm traceForm in this.AllTraceDocumentForms)
				traceForm.Refresh();
		}
		#endregion
        #region IFormStatusbar Members
        void IFormStatusbar.StatusBarSet(StatusBarItem item, object value)
        {
            ((IFormStatusbar)this._StatusBar).StatusBarSet(item, value);
        }
        #endregion
	}
}
